//
//  NSData+JwCate.m
//  JwPack
//
//  Created by 陈警卫 on 2024-07-18.
//

#import "NSData+JwCate.h"
#include <CommonCrypto/CommonCrypto.h>

@implementation NSData (JwCate)

/// 解析JSON
- (NSDictionary *)jw_json {
    NSError *error = nil;
    id value = [NSJSONSerialization JSONObjectWithData:self options:kNilOptions error:&error];
    if (error) {
        NSLog(@"jw_json error:%@", error);
    }
    if (![value isKindOfClass:[NSDictionary class]]) {
        NSLog(@"jw_json 警告: 返回的对象不是字典");
    }
    return value;
}

/// data转16进制字符串
- (NSString *)jw_hexString {
    if (self.length <= 0) {
        return @"";
    }
    Byte *bytes = (Byte *)[self bytes];
    NSMutableString *hexString = [[NSMutableString alloc] init];
    NSUInteger length = [self length];
    for (NSUInteger i = 0; i < length; i++) {
        [hexString appendFormat:@"%02X", bytes[i]];
    }
    return hexString;
}

/// data转2进制字符串
- (NSString *)jw_binaryString {
    if (self.length <= 0) {
        return @"";
    }
    Byte *bytes = (Byte *)[self bytes];
    NSMutableString *binaryString = [[NSMutableString alloc] init];
    NSUInteger length = [self length];
    for (NSUInteger i = 0; i < length; i++) {
        [binaryString appendFormat:@"%08u", bytes[i]];
    }
    return binaryString;
}

/// data转ascii字符串
- (NSString *)jw_asciiString {
    if (self.length <= 0) {
        return @"";
    }
    NSMutableString *asciiStr = [[NSMutableString alloc] init];
    Byte *bytes = (Byte *)[self bytes];
    for (int i = 0; i < self.length; i++) {
        [asciiStr appendFormat:@"%c", bytes[i]];
    }
    return asciiStr;
}

/// data转ascii字符串
- (NSString *)jw_asciiStringCorrect {
    if (self.length <= 0) {
        return @"";
    }
    NSMutableString *asciiStr = [[NSMutableString alloc] init];
    Byte *bytes = (Byte *)[self bytes];
    for (int i = 0; i < self.length; i++) {
        uint8_t value = bytes[i];
        if (value == 0) {
            break;
        }
        [asciiStr appendFormat:@"%c", bytes[i]];
    }
    return asciiStr;
}

/// 反转字节序列代码
- (NSData *)jw_dataReverse {
    NSUInteger byteCount = self.length;
    NSMutableData *dstData = [[NSMutableData alloc] initWithData:self];
    NSUInteger halfLength = byteCount / 2;
    for (NSUInteger i = 0; i < halfLength; i++) {
        NSRange begin = NSMakeRange(i, 1);
        NSRange end = NSMakeRange(byteCount - i - 1, 1);
        NSData *beginData = [self subdataWithRange:begin];
        NSData *endData = [self subdataWithRange:end];
        [dstData replaceBytesInRange:begin withBytes:endData.bytes];
        [dstData replaceBytesInRange:end withBytes:beginData.bytes];
    }
    return dstData;
}

/// data转NSInteger
- (NSInteger)jw_integer {
    NSInteger i = 0;
    [self getBytes:&i length:sizeof(i)];
    return i;
}

/// data转int8
- (int8_t)jw_int8 {
    int8_t value = [self jw_integer];
    return value;
}

/// data转int16
- (int16_t)jw_int16 {
    int16_t value = [self jw_integer];
    return value;
}

/// data转int32
- (int32_t)jw_int32 {
    int32_t value = (int32_t)[self jw_integer];
    return value;
}

/// data转NSUInteger
- (NSUInteger)jw_uint:(NSUInteger)len {
    Byte *bytes = (Byte *)[self bytes];
    NSUInteger length = MIN(len, [self length]);
    length = length == 0 ? [self length] : length;
    
    NSUInteger value = 0;
    for (NSUInteger i = 0; i < length; i++) {
        value += (bytes[i] << (i * 8));
    }
    return value;
}

/// data转uint8
- (uint8_t)jw_uint8 {
    uint8_t value = [self jw_uint:1];
    return value;
}

/// data转uint16
- (uint16_t)jw_uint16 {
    uint16_t value = [self jw_uint:2];
    return value;
}

/// data转uint32
- (uint32_t)jw_uint32 {
    uint32_t value = (uint32_t)[self jw_uint:4];
    return value;
}

/// int转data(大小端)
+ (NSData *)jw_dataWithInt:(NSInteger)value length:(NSUInteger)length {
    NSData *valueData = [NSData dataWithBytes:&value length:length];
    return valueData;
}

/// int转data(大小端)
+ (NSData *)jw_dataWithInt:(NSInteger)value len:(NSUInteger)len {
    Byte bytes[len];
    for (NSUInteger i = 0; i < len; i++) {
        bytes[i] = (value >> (i * 8)) & 0xFF;
    }
    NSData *valueData = [NSData dataWithBytes:&bytes length:len];
    return valueData;
}

/// int转data
+ (NSData *)jw_dataNtohWithInt:(NSInteger)value length:(NSUInteger)length {
    NTOHS(value);
    NSData *valueData = [NSData dataWithBytes:&value length:length];
    return valueData;
}

/// 获取data二进制下标的值 方向右左 <-
- (NSInteger)jw_binaryWithIndex:(NSInteger)index {
    NSInteger len = self.length * 8;
    if (index >= len) {
        return 0;
    }
    NSInteger bitMask = 1 << index;
    uint8_t *bytes = (uint8_t *)[self bytes];
    NSInteger byteIndex = index / 8;
    NSInteger bitIndex = index % 8;
    NSInteger value = (bytes[byteIndex] & (bitMask >> bitIndex)) >> bitIndex;
    return value;
}

/// 获取data二进制范围内值 方向右左 <-
- (NSInteger)jw_binaryWithRange:(NSRange)range {
    NSInteger len = self.length * 8;
    NSInteger locs = range.location;
    NSInteger loce = range.location + range.length - 1;
    
    if (loce >= len || locs < 0) {
        return 0;
    }
    NSInteger startBitMask = 1 << (len - locs - 1);
    NSInteger endBitMask = 1 << (len - loce - 1);
    
    uint8_t *bytes = (uint8_t *)[self bytes];
    NSInteger byteStartIndex = locs / 8;
    NSInteger byteEndIndex = loce / 8;
    
    NSInteger result = 0;
    NSInteger bitShift = locs % 8;
    
    for (NSInteger i = byteStartIndex; i <= byteEndIndex; i++) {
        NSInteger currentByte = bytes[i];
        
        if (i == byteStartIndex) {
            currentByte &= ~((1 << bitShift) - 1);
            currentByte <<= range.length - bitShift;
        } else if (i == byteEndIndex) {
            currentByte >>= (8 - (range.length - (i - byteStartIndex) * 8));
        }
        result |= currentByte;
    }
    result >>= (range.length - (byteEndIndex - byteStartIndex) * 8);
    return result;
}


/// md5 Data
- (NSData *)jw_md5Data {
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5(self.bytes, (CC_LONG)self.length, result);
    return [NSData dataWithBytes:result length:CC_MD5_DIGEST_LENGTH];
}

/// md5 String
- (NSString *)jw_md5String {
    return [[self jw_md5Data] jw_hexString];
}

/// CRC-16/CCITT-FALSE x16+x12+x5+1
- (unsigned short)jw_crc {
    int start = 0;
    int end = (uint16_t)[self length];
    unsigned short crc = 0xffff;
    unsigned short polynomial = 0x1021;
    Byte codeKeyByteAry[self.length];
    for (int i = 0; i < self.length; i++) {
        NSData *idata = [self subdataWithRange:NSMakeRange(i, 1)];
        codeKeyByteAry[i] = ((Byte*)[idata bytes])[0];
    }
    for (int index = start; index < end; index++){
        Byte b = codeKeyByteAry[index];
        for (int i = 0; i < 8; i++) {
            Boolean bit = ((b >> (7 - i) & 1) == 1);
            Boolean c15 = ((crc >> 15 & 1) == 1);
            crc <<= 1;
            if (c15 ^ bit)
                crc ^= polynomial;
        }
    }
    crc &= 0xffff;
    return crc;
}

/// CRC-16/CCITT-FALSE x16+x12+x5+1
- (NSData *)jw_crcData {
    Byte crcByte[2] = {0x00, 0x00};
    unsigned int crcInt = [self jw_crc];
    memcpy(&crcByte, &crcInt, 2);
    NSData *sumData = [NSData dataWithBytes:&crcByte length:sizeof(crcByte)];
    return sumData;
}

/// CRC-16/CCITT-FALSE x16+x12+x5+1
- (NSString *)jw_crcString {
    return [[self jw_crcData] jw_hexString];
}


@end
